package com.wawi.common;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jodd.util.ArraysUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wawi.common.annotation.Logs;
import cn.wawi.dao.sys.LogDao;
import cn.wawi.entity.sys.Log;
import cn.wawi.entity.sys.User;
import com.wawi.utils.StringEscapeUtil;
import com.wawi.utils.StringUtil;
import eu.bitwalker.useragentutils.UserAgent;

/**
 * @description AOP注解实现系统日志记录,及 全局异常处理
 * @version V1.0.0
 * @author 龚亮
 * @date 2015-05-26 11:32:09
 */
@Component
@Aspect
@SuppressWarnings("all")
public class LoggerAdvice{
	
    @Resource(name="mappingJackson2HttpMessageConverter")
    private MappingJackson2HttpMessageConverter converter;
    @Resource
    private LogDao<Log> logDao;
	private static Logger logger = Logger.getLogger(LoggerAdvice.class);

	/*环绕通知*/
	@Around("within(cn.wawi.controller..*) && @annotation(logs)")
	public Object doAround(ProceedingJoinPoint p,Logs logs) throws Throwable{
		String isSuccess="1";
		HttpServletRequest request=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
		Log log=new Log(logs.des(),StringUtil.getIpAddr(request));
		String requestRri = request.getRequestURI();
		String uriPrefix = request.getContextPath();
		String operationCode=StringUtils.substringAfter(requestRri,uriPrefix);	//操作编码
		log.setOperationCode(operationCode);
		HashMap map=new HashMap(request.getParameterMap()); 
		if(map.containsKey("password")){
			map.put("password", new String[]{"******"});
		}
		String requestParam=new ObjectMapper().writeValueAsString(map);	//请求参数
		log.setRequestParam(requestParam);
		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); 
		String os=userAgent.getOperatingSystem().getName();	//获取客户端操作系统
		String browser=userAgent.getBrowser().getName();	//获取客户端浏览器
		log.setOs(os);
		log.setBrowser(browser);
		Object obj =null;
		try {
			obj =p.proceed();
		} catch (Throwable e) {
			isSuccess="0";
			logger.error("发生异常："+e.getMessage());
			throw e;
		}finally{
			log.setIsSuccess(isSuccess);
			User user=(User) request.getSession().getAttribute("loginUser");
			if(user!=null){
				log.setRealname(user.getRealname());
				log.setOptUser(user.getUsername());
			}
			logDao.saveOne(log);
		}
		return obj;
	}
	/*环绕通知*/
	//@Around("within(cn.wawi.controller..*) && @annotation(org.springframework.web.bind.annotation.ResponseBody)")
	public Object doAround(ProceedingJoinPoint p) throws Throwable{
		Object obj =p.proceed();
		return obj;
	}
	/**
	 * 全局异常处理
	 */
	public void doException(JoinPoint p,Throwable e){
		Class<?> targetClass=null;
		HttpServletResponse response=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
		try {
			targetClass = Class.forName(p.getTarget().getClass().getName());
			Method[] method = targetClass.getMethods(); 
			String methodName = p.getSignature().getName();  
			for(Method m: method){
				if(m.getName().equals(methodName)){
					if(m.isAnnotationPresent(ResponseBody.class)){
						ResultData json=new ResultData();
						json.setResCode("1");
						json.setResMsg("请求失败!");
				        HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
				        converter.write(json, MediaType.APPLICATION_JSON, outputMessage);
				        shutdownResponse(response);
					}
				}
			}
		} catch (Exception e1) {
			logger.error("发生异常："+e1.getMessage());
			e1.printStackTrace();
		}  
	}
	/*例外通知*/
	@AfterThrowing(pointcut="within(cn.wawi.controller..*)",throwing="e")
	public void doAfterThrowing(JoinPoint joinPoint,Exception e){
       doException(joinPoint, e);
	}
	/*最终通知
	@AfterReturning("within(cn.wawi.controller..*)&& @annotation(logs)")
	public void doFinally(JoinPoint jp,Logs logs){
		HttpServletRequest request=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
		Log log=new Log(jp.getTarget().getClass().getName(),jp.getSignature().getName(),logs.des());
		log.setIsSuccess(isSuccess);
		User user=(User) request.getSession().getAttribute("loginUser");
		if(user!=null){
			log.setRealname(user.getRealname());
			log.setOptUser(user.getUsername());
		}
		System.out.println("保存日志....."+log.getIsSuccess()+":"+log.getActionName()+":"+log.getMethodName()+":"+log.getDescription()+":"+log.getOptUser());
	}*/
    public void shutdownResponse(HttpServletResponse response) throws IOException{
        response.getOutputStream().close();
    }
    /*前置通知
	@Before("within(cn.wawi.controller..*)")
	public void doBefore(JoinPoint jp){
		String info="前置通知:"+jp.getTarget().getClass().getName()+","+jp.getSignature().getName();
		System.out.println(info);
	}*/
	 /*后置通知
	@After("within(cn.wawi.controller..*)")
	public void doAfter(JoinPoint jp){
		String info="后置通知:"+jp.getTarget().getClass().getName()+","+jp.getSignature().getName();
		System.out.println(info);
	}*/
}
